#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>

#include "ui_curses.h"

UI *ui_new()
{
    UI *u = malloc(sizeof(UI));

    u->mainwnd = initscr();

    u->mainpad = NULL;
    char *content_template = NULL;

    noecho();
    cbreak();
    nodelay(u->mainpad, TRUE);
    /*
    refresh();     
    wrefresh(u->mainpad);
    scrollok(u->mainpad, TRUE);
    */

    return u;
}

void ui_delete(UI *u)
{
    
}

void ui_init_and_run(UI *u)
{
    /*
    start_color();

    init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
    init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
    init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
    init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
    init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
    init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
    init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
    init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);

    */
    curs_set(0);

    char *text = "Hello, this is a simple title\n\nThis page now supports newlines as you can see. We hope to be adding 'justify' text soon.\nThanks for checking out our product.\n\n\nTraduzione:\n\nQuesta pagina contiene newlines. Speriamo di aggiungere supporto per testo 'justified' in modo da rendere l'esperienza piu' gradevole. Grazie per avere scaricato il nostro software.\n\n**REPEAT FOR TESTING LONG TEXT**\n\nHello, this is a simple title\n\nThis page now supports newlines as you can see. We hope to be adding 'justify' text soon.\nThanks for checking out our product.\n\n\nTraduzione:\n\nQuesta pagina contiene newlines. Speriamo di aggiungere supporto per testo 'justified' in modo da rendere l'esperienza piu' gradevole. Grazie per avere scaricato il nostro software.\n\n**REPEAT FOR TESTING LONG TEXT**\n\nHello, this is a simple title\n\nThis page now supports newlines as you can see. We hope to be adding 'justify' text soon.\nThanks for checking out our product.\n\n\nTraduzione:\n\nQuesta pagina contiene newlines. Speriamo di aggiungere supporto per testo 'justified' in modo da rendere l'esperienza piu' gradevole. Grazie per avere scaricato il nostro software.\n\n**REPEAT FOR TESTING LONG TEXT**\n\nHello, this is a simple title\n\nThis page now supports newlines as you can see. We hope to be adding 'justify' text soon.\nThanks for checking out our product.\n\n\nTraduzione:\n\nQuesta pagina contiene newlines. Speriamo di aggiungere supporto per testo 'justified' in modo da rendere l'esperienza piu' gradevole. Grazie per avere scaricato il nostro software.\n\n**REPEAT FOR TESTING LONG TEXT**\n\nHello, this is a simple title\n\nThis page now supports newlines as you can see. We hope to be adding 'justify' text soon.\nThanks for checking out our product.\n\n\nTraduzione:\n\nQuesta pagina contiene newlines. Speriamo di aggiungere supporto per testo 'justified' in modo da rendere l'esperienza piu' gradevole. Grazie per avere scaricato il nostro software.";

    /* while(1) in here */
    ui_run(u, text); 

}

void ui_run(UI *u, char *text)
{
    /* initialize */
    int posx = 0, posy = 0;
    int screenh = 0, screenw = 0, oldh, oldw;
    
    getmaxyx(u->mainwnd, screenh, screenw);

    /* create new pad with content dimension;
     * delete the pad, and recreate it on each window resize. 
     * we don't know the height of the content yet because 
     * we still have to generate it;
     * generate it based on the 'screenw', and add to pad later?
     */

    /* generate height from content */
    ui_generate_height(u, text, screenw);

    /* create new pad, with the calculated height of the content */
    u->mainpad = newpad(u->content_height, screenw);

    ui_update_content(u, text, screenw);

    /* first refresh */
    wrefresh(u->mainwnd);
    
    int ch, ret;
    while(1) {
        /* get screen size */
        oldh = screenh;
        oldw = screenw;

        getmaxyx(u->mainwnd, screenh, screenw);

        /* resized window? lets refresh properties */
        if((screenh != oldh) || (screenw != oldw)) {
            if(oldh > 0) {
                /* let's delete the pad */
                delwin(u->mainpad);
            }
            /* lets clear the screen */
            erase();

            /* generate height from content */
            ui_generate_height(u, text, screenw);

            /* create new one with width of the resized window 
             * and the height of the generated content */
            u->mainpad = newpad(u->content_height, screenw);

            /* update content with new screen size */
            ui_update_content(u, text, screenw);
            
            wrefresh(u->mainwnd);
        }

        /* check and fix positions FIXME */
        if(posy < 0 || screenh >= u->content_height) {
            posy = 0;
        } else if ((screenh + posy) > u->content_height) {
            posy = u->content_height - screenh;
        }

        //mvwprintw(u->mainpad, 10, 0, "---content_height: %d, screenh: %d, posy: %d----", u->content_height, screenh, posy);

        /* FIXME not sure why it needs -1  */
        prefresh(u->mainpad, posy, posx, 0, 0, screenh-1, screenw);

        ch = getch(); // blocks (hrm, guess this doesn't block)
        ret = ui_handle_keystroke(u, ch);
        if(ret == -1) {
            break;
        } else if(ch == 107) { /* k */
            posy--;
        } else if(ch == 106) {
            posy++;
        }
    }

    endwin();
}

void ui_update_content(UI *u, char *text, int screenw)
{
    /* must generate content based on content_template FIXME */
    /* add the text to it, char by char so we can wrap. y-x = 0-0; */
    int i, y, x;
    for(i=0, y=0, x=i; text[i] != '\0'; i++, x++) {
        if(x == screenw) { // we need to wrap now
            y++;
            x = 0;
        }
        /* replace new lines with visual line break */
        if(text[i] == '\n') {
            y++; 
            x = -1; /* reset horizontal line, -1 because next iteration x needs to start from 0 */
        } else { /* else, because we don't want to print the \n */
            mvwaddch(u->mainpad, y, x, text[i]);
        }
    }
}

void ui_generate_height(UI *u, char *text, int screenw)
{
    /* must generate height based on the content_template FIXME */
    /* for now it's using a plain template */
    int i, y, x;
    for(i=0, y=0, x=i; text[i] != '\0'; i++, x++) {
        if(x == screenw) { // we need to wrap now
            y++;
            x = 0;
        }
        if(text[i] == '\n') {
            y++; 
            x = -1; /* reset horizontal line, -1 because next iteration x needs to start from 0 */
        }
    }

    u->content_height = y+1; /* -1 because 'y' starts from 0 */
}

int ui_handle_keystroke(UI *u, int ch)
{
    if(ch == 113) { // pressed 'q'
        return -1; 
    } else if(ch == 106) { // 'j'
        /* scroll down */

        return 0;
    } else if(ch == 107) { // 'k'
        /* scroll up */

        return 0;
    }
}
List_item *list_item_new()
{
    List_item *litem = malloc(sizeof(List_item));
    litem->cury = 0;
    litem->itemheight = 4;
    litem->title = "CIAO STRONZO";
}
void list_item_delete(List_item *litem)
{
    free(litem);
}
void list_item_add(UI *u, List_item *litem)
{
    litem->cury = litem->cury + litem->itemheight;
    /* mvwprintw takes care with copying (probably strdup) the chars into its own memory space */
    mvwprintw(u->mainpad, litem->cury, 0, litem->title);
}
